// Copyright©,2020-2025
// Author: caocheng
// Version: 1.0.0
// Date: 2021/3/8 14:10
// Description：
package SummerStarter

import (
	"context"

	"gitee.com/chrischo/go-summer/summer/summer-boot"
	"gitee.com/chrischo/go-summer/summer/summer-core"
	"gitee.com/chrischo/go-summer/summer/summer-utils"
	"gitee.com/chrischo/go-summer/summer/summer-web"
)

// WebServerStarter Web 服务器启动器
type WebServerStarter struct {
	WebServer *SummerWeb.WebServer
}

func NewWebServerStarter() *WebServerStarter {
	return &WebServerStarter{
		WebServer: SummerWeb.NewWebServer(),
	}
}

func (starter *WebServerStarter) OnStartApplication(ctx SummerBoot.ApplicationContext) {
	// 处理 WebServer 级别的过滤器，排除不满足条件的过滤器
	starter.WebServer.ResetFilters(starter.resolveFilters(ctx, starter.WebServer.Filters()))

	for _, c := range starter.WebServer.Containers() {

		// 处理 WebContainer 级别的过滤器，排除不满足条件的过滤器
		c.ResetFilters(starter.resolveFilters(ctx, c.GetFilters()))

		for _, mapping := range SummerBoot.DefaultWebMapping.Mappings {

			// 查看路由的端口是否匹配
			ports := mapping.Ports()
			if len(ports) > 0 && SummerUtils.ContainsInt(ports, c.Config().Port) < 0 {
				continue
			}

			// 查看路由的条件是否匹配
			if !mapping.CheckCondition(ctx) {
				continue
			}

			// 处理 Mapping 级别的过滤器，排除不满足条件的过滤器
			filters := starter.resolveFilters(ctx, mapping.Filters())
			mapper := SummerWeb.NewMapper(mapping.Method(), mapping.Path(), mapping.Handler(), filters)
			c.AddMapper(mapper.WithSwagger(mapping.Swagger()))
		}
	}

	// 容器运行过程中自身发生错误的退出程序，尤其像端口占用这种错误
	starter.WebServer.SetErrorCallback(func(err error) {
		SummerCore.Exit()
	})

	starter.WebServer.Start()
}

func (starter *WebServerStarter) resolveFilters(ctx SummerCore.ApplicationContext, filters []SummerWeb.Filter) []SummerWeb.Filter {
	var result []SummerWeb.Filter
	for _, filter := range filters {
		switch f := filter.(type) {
		case *SummerBoot.ConditionalWebFilter:
			result = append(result, f.ResolveFilters(ctx)...)
		default:
			result = append(result, f)
		}
	}
	return result
}

func (starter *WebServerStarter) OnStopApplication(ctx SummerBoot.ApplicationContext) {
	starter.WebServer.Stop(context.Background())
}
